home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch17 / TChecker.cls < prev    next >
Text File  |  1999-07-10  |  19KB  |  576 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "RayMappedCheckerboard"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = False
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' A textured checkerboard in a plane.
  17.  
  18. Implements RayTraceable
  19.  
  20. ' The texture picture's pixels.
  21. Private TexturePixels() As RGBTriplet
  22.  
  23. Private Point1 As Point3D       ' Point on corner.
  24. Private Point2 As Point3D       ' Point on 1st corner of first rectangle.
  25. Private Point3 As Point3D       ' Point on 2nd corner of first rectangle.
  26. Private NumSquares1 As Integer  ' # squares in 1st direction.
  27. Private NumSquares2 As Integer  ' # squares in 2nd direction.
  28.  
  29. ' Ambient light parameters.
  30. Private AmbientFactor As Single
  31.  
  32. ' Diffuse light parameters.
  33. Private DiffuseFactor As Single
  34.  
  35. ' Specular reflection parameters.
  36. Private SpecularN As Single
  37. Private SpecularK As Single
  38.  
  39. ' Reflected light parameters.
  40. Private ReflectedKr As Single
  41. Private ReflectedKg As Single
  42. Private ReflectedKb As Single
  43.  
  44. ' Refracted light parameters.
  45. Private TransN As Single
  46. Private n1 As Single   ' Index of refraction outside the object.
  47. Private n2 As Single   ' Index of refraction inside the object.
  48. Private TransmittedKr As Single
  49. Private TransmittedKg As Single
  50. Private TransmittedKb As Single
  51.  
  52. Private IsReflective As Boolean
  53. Private IsTransparent As Boolean
  54. Private DoneOnThisScanline As Boolean
  55.  
  56. ' We had a hit on this scanline.
  57. Private HadHit As Boolean
  58.  
  59. ' We have had a hit on a previous scanline.
  60. Private HadHitOnPreviousScanline As Boolean
  61.  
  62. ' We will not be visible on later scanlines.
  63. Private ForeverCulled As Boolean
  64. ' Get the point's checkerboard coordinates.
  65. ' Return True if the point is on a square.
  66. Private Function GetCheckerboardCoordinates(ByRef i As Single, ByRef j As Single, ByVal X As Single, ByVal Y As Single, ByVal Z As Single) As Boolean
  67. Dim px As Single
  68. Dim py As Single
  69. Dim pz As Single
  70. Dim v1x As Single
  71. Dim v1y As Single
  72. Dim v1z As Single
  73. Dim v2x As Single
  74. Dim v2y As Single
  75. Dim v2z As Single
  76.  
  77.     ' Get the square vectors.
  78.     px = Point1.Trans(1)
  79.     py = Point1.Trans(2)
  80.     pz = Point1.Trans(3)
  81.     v1x = Point2.Trans(1) - px
  82.     v1y = Point2.Trans(2) - py
  83.     v1z = Point2.Trans(3) - pz
  84.     v2x = Point3.Trans(1) - px
  85.     v2y = Point3.Trans(2) - py
  86.     v2z = Point3.Trans(3) - pz
  87.  
  88.     ' Get the i and j values for this point.
  89.     If (Abs(v1x) > 0.001) And (Abs(v1y * v2x - v2y * v1x) > 0.001) Then
  90.         j = (v1y * (X - px) + v1x * (py - Y)) / (v1y * v2x - v2y * v1x)
  91.         i = (X - px - v2x * j) / v1x
  92.     ElseIf (Abs(v1y) > 0.001) And (Abs(v1z * v2y - v2z * v1y) > 0.001) Then
  93.         j = (v1z * (Y - py) + v1y * (pz - Z)) / (v1z * v2y - v2z * v1y)
  94.         i = (Y - py - v2y * j) / v1y
  95.     Else
  96.         j = (v1x * (Z - pz) + v1z * (px - X)) / (v1x * v2z - v2x * v1z)
  97.         i = (Z - pz - v2z * j) / v1z
  98.     End If
  99.  
  100.     ' See if the point is ok.
  101.     If (i < 0) Or (j < 0) Or (i > NumSquares1) Or (j > NumSquares2) Then
  102.         ' Not on the area of interest.
  103.         GetCheckerboardCoordinates = False
  104.     ElseIf (Int(i) + Int(j)) Mod 2 <> 0 Then
  105.         ' Not on a drawn square.
  106.         GetCheckerboardCoordinates = False
  107.     Else
  108.         ' We had a hit.
  109.         GetCheckerboardCoordinates = True
  110.     End If
  111. End Function
  112.  
  113. ' Return an appropriate color for this object.
  114. Private Function GetColor() As Long
  115. Dim R As Integer
  116. Dim G As Integer
  117. Dim B As Integer
  118.  
  119.     R = 255 * (DiffuseFactor + AmbientFactor): If R > 255 Then R = 255
  120.     G = R
  121.     B = R
  122.     GetColor = RGB(R, G, B)
  123. End Function
  124. ' Return the right shade for this polygon.
  125. Private Function GetShade(ByVal pgon As SimplePolygon) As Long
  126. Dim i As Integer
  127. Dim px As Single
  128. Dim py As Single
  129. Dim pz As Single
  130. Dim light_source As LightSource
  131. Dim total_r As Single
  132. Dim total_g As Single
  133. Dim total_b As Single
  134. Dim R1 As Integer
  135. Dim g1 As Integer
  136. Dim b1 As Integer
  137. Dim empty_objects As Collection
  138.  
  139.     With pgon
  140.         ' Find a central point on this polygon.
  141.         For i = 1 To .PointX.Count
  142.             px = px + .PointX(i)
  143.             py = py + .PointY(i)
  144.             pz = pz + .PointZ(i)
  145.         Next i
  146.         px = px / .PointX.Count
  147.         py = py / .PointX.Count
  148.         pz = pz / .PointX.Count
  149.  
  150.         ' Add up the light components.
  151.         Set empty_objects = New Collection
  152.         For Each light_source In LightSources
  153.             CalculateHitColorDSA _
  154.                 1, empty_objects, Nothing, _
  155.                 EyeX, EyeY, EyeZ, _
  156.                 px, py, pz, .Nx, .Ny, .Nz, _
  157.                 DiffuseFactor, DiffuseFactor, DiffuseFactor, _
  158.                 AmbientFactor, AmbientFactor, AmbientFactor, _
  159.                 SpecularK, SpecularN, R1, g1, b1
  160.             total_r = total_r + R1
  161.             total_g = total_g + g1
  162.             total_b = total_b + b1
  163.         Next light_source
  164.     End With
  165.  
  166.     If total_r > 255 Then total_r = 255
  167.     If total_g > 255 Then total_g = 255
  168.     If total_b > 255 Then total_b = 255
  169.  
  170.     GetShade = RGB(total_r, total_g, total_b)
  171. End Function
  172.  
  173. ' Return the unit surface normal.
  174. Private Sub GetUnitNormal(ByRef Nx As Single, ByRef Ny As Single, ByRef Nz As Single)
  175. Dim v1x As Single
  176. Dim v1y As Single
  177. Dim v1z As Single
  178. Dim v2x As Single
  179. Dim v2y As Single
  180. Dim v2z As Single
  181. Dim n_len As Single
  182.  
  183.     ' Get the square vectors.
  184.     v1x = Point2.Trans(1) - Point1.Trans(1)
  185.     v1y = Point2.Trans(2) - Point1.Trans(2)
  186.     v1z = Point2.Trans(3) - Point1.Trans(3)
  187.     v2x = Point3.Trans(1) - Point1.Trans(1)
  188.     v2y = Point3.Trans(2) - Point1.Trans(2)
  189.     v2z = Point3.Trans(3) - Point1.Trans(3)
  190.  
  191.     ' Calculate the normal.
  192.     m3Cross Nx, Ny, Nz, v1x, v1y, v1z, v2x, v2y, v2z
  193.     n_len = Sqr(Nx * Nx + Ny * Ny + Nz * Nz)
  194.     Nx = Nx / n_len
  195.     Ny = Ny / n_len
  196.     Nz = Nz / n_len
  197. End Sub
  198. ' Add non-backface polygons to this collection.
  199. Public Sub RayTraceable_GetPolygons(ByRef num_polygons As Integer, polygons() As SimplePolygon, ByVal shaded As Boolean)
  200. Dim pgon As SimplePolygon
  201. Dim px As Single
  202. Dim py As Single
  203. Dim pz As Single
  204. Dim v1x As Single
  205. Dim v1y As Single
  206. Dim v1z As Single
  207. Dim v2x As Single
  208. Dim v2y As Single
  209. Dim v2z As Single
  210. Dim i As Integer
  211. Dim j As Integer
  212.  
  213.     ' Get the square vectors.
  214.     px = Point1.Trans(1)
  215.     py = Point1.Trans(2)
  216.     pz = Point1.Trans(3)
  217.     v1x = Point2.Trans(1) - px
  218.     v1y = Point2.Trans(2) - py
  219.     v1z = Point2.Trans(3) - pz
  220.     v2x = Point3.Trans(1) - px
  221.     v2y = Point3.Trans(2) - py
  222.     v2z = Point3.Trans(3) - pz
  223.  
  224.     ' Make the squares.
  225.     For i = 0 To NumSquares1 - 1
  226.         For j = 0 To NumSquares2 - 1
  227.             If (i + j) Mod 2 = 0 Then
  228.                 ' Make a polygon.
  229.                 Set pgon = New SimplePolygon
  230.                 pgon.AddPoint px + i * v1x + j * v2x, py + i * v1y + j * v2y, pz + i * v1z + j * v2z
  231.                 pgon.AddPoint px + (i + 1) * v1x + j * v2x, py + (i + 1) * v1y + j * v2y, pz + (i + 1) * v1z + j * v2z
  232.                 pgon.AddPoint px + (i + 1) * v1x + (j + 1) * v2x, py + (i + 1) * v1y + (j + 1) * v2y, pz + (i + 1) * v1z + (j + 1) * v2z
  233.                 pgon.AddPoint px + i * v1x + (j + 1) * v2x, py + i * v1y + (j + 1) * v2y, pz + i * v1z + (j + 1) * v2z
  234.  
  235.                 ' See if we are shaded.
  236.                 If shaded Then
  237.                     ' We are shaded. Get the right color.
  238.                     pgon.ForeColor = GetShade(pgon)
  239.                     pgon.FillColor = pgon.ForeColor
  240.                 Else
  241.                     ' We are not shaded. Use the normal colors.
  242.                     pgon.ForeColor = vbBlack
  243.                     pgon.FillColor = GetColor()
  244.                 End If
  245.  
  246.                 ' Add the polygon to the list.
  247.                 num_polygons = num_polygons + 1
  248.                 ReDim Preserve polygons(1 To num_polygons)
  249.                 Set polygons(num_polygons) = pgon
  250.             End If
  251.         Next j
  252.     Next i
  253. End Sub
  254. ' Draw a wireframe for this object.
  255. Public Sub RayTraceable_DrawWireFrame(ByVal pic As PictureBox)
  256. Dim px As Single
  257. Dim py As Single
  258. Dim v1x As Single
  259. Dim v1y As Single
  260. Dim v2x As Single
  261. Dim v2y As Single
  262. Dim i As Integer
  263. Dim j As Integer
  264.  
  265.     ' Use an appropriate color.
  266.     pic.ForeColor = GetColor()
  267.  
  268.     ' Get the square vectors.
  269.     px = Point1.Trans(1)
  270.     py = Point1.Trans(2)
  271.     v1x = Point2.Trans(1) - px
  272.     v1y = Point2.Trans(2) - py
  273.     v2x = Point3.Trans(1) - px
  274.     v2y = Point3.Trans(2) - py
  275.  
  276.     ' Draw the squares.
  277.     For i = 0 To NumSquares1 - 1
  278.         For j = 0 To NumSquares2 - 1
  279.             If (i + j) Mod 2 = 0 Then
  280.                 pic.Line (px + i * v1x + j * v2x, py + i * v1y + j * v2y)-(px + (i + 1) * v1x + j * v2x, py + (i + 1) * v1y + j * v2y)
  281.                 pic.Line -(px + (i + 1) * v1x + (j + 1) * v2x, py + (i + 1) * v1y + (j + 1) * v2y)
  282.                 pic.Line -(px + i * v1x + (j + 1) * v2x, py + i * v1y + (j + 1) * v2y)
  283.                 pic.Line -(px + i * v1x + j * v2x, py + i * v1y + j * v2y)
  284.             End If
  285.         Next j
  286.     Next i
  287. End Sub
  288.  
  289. ' Initialize the object using text parameters in
  290. ' a comma-delimited list.
  291. Public Sub SetParameters(ByVal pic As PictureBox, ByVal txt As String)
  292. Dim file_name As String
  293. Dim bits_per_pixel As Integer
  294.  
  295.     On Error GoTo CheckerboardParamError
  296.  
  297.     ' Read the parameters and initialize the object.
  298.     ' Load the texture file.
  299.     file_name = GetDelimitedToken(txt, ",")
  300.     pic.AutoSize = True
  301.     pic.AutoRedraw = True
  302.     pic.Picture = LoadPicture(file_name)
  303.     GetBitmapPixels pic, TexturePixels, bits_per_pixel
  304.  
  305.     ' Geometry.
  306.     NumSquares1 = CInt(GetDelimitedToken(txt, ","))
  307.     NumSquares2 = CInt(GetDelimitedToken(txt, ","))
  308.     Point1.Coord(1) = CSng(GetDelimitedToken(txt, ","))
  309.     Point1.Coord(2) = CSng(GetDelimitedToken(txt, ","))
  310.     Point1.Coord(3) = CSng(GetDelimitedToken(txt, ","))
  311.     Point1.Coord(4) = 1
  312.     Point2.Coord(1) = CSng(GetDelimitedToken(txt, ","))
  313.     Point2.Coord(2) = CSng(GetDelimitedToken(txt, ","))
  314.     Point2.Coord(3) = CSng(GetDelimitedToken(txt, ","))
  315.     Point2.Coord(4) = 1
  316.     Point3.Coord(1) = CSng(GetDelimitedToken(txt, ","))
  317.     Point3.Coord(2) = CSng(GetDelimitedToken(txt, ","))
  318.     Point3.Coord(3) = CSng(GetDelimitedToken(txt, ","))
  319.     Point3.Coord(4) = 1
  320.  
  321.     ' Ambient light.
  322.     AmbientFactor = CSng(GetDelimitedToken(txt, ","))
  323.  
  324.     ' Diffuse reflection.
  325.     DiffuseFactor = CSng(GetDelimitedToken(txt, ","))
  326.  
  327.     ' Specular reflection.
  328.     SpecularN = CSng(GetDelimitedToken(txt, ","))
  329.     SpecularK = CSng(GetDelimitedToken(txt, ","))
  330.  
  331.     ' Reflected light.
  332.     ReflectedKr = CSng(GetDelimitedToken(txt, ","))
  333.     ReflectedKg = CSng(GetDelimitedToken(txt, ","))
  334.     ReflectedKb = CSng(GetDelimitedToken(txt, ","))
  335.     IsReflective = (ReflectedKr > 0) Or (ReflectedKg > 0) Or (ReflectedKb > 0)
  336.  
  337.     ' Transmitted light.
  338.     TransN = CSng(GetDelimitedToken(txt, ","))
  339.     n1 = CSng(GetDelimitedToken(txt, ","))
  340.     n2 = CSng(GetDelimitedToken(txt, ","))
  341.     TransmittedKr = CSng(GetDelimitedToken(txt, ","))
  342.     TransmittedKg = CSng(GetDelimitedToken(txt, ","))
  343.     TransmittedKb = CSng(GetDelimitedToken(txt, ","))
  344.     IsTransparent = (TransmittedKr > 0) Or (TransmittedKg > 0) Or (TransmittedKb > 0)
  345.  
  346.     Exit Sub
  347.  
  348. CheckerboardParamError:
  349.     MsgBox "Error initializing checkerboard parameters."
  350. End Sub
  351.  
  352. ' Apply a transformation matrix to the object.
  353. Public Sub RayTraceable_Apply(M() As Single)
  354.     ' Transform the points.
  355.     m3Apply Point1.Coord, M, Point1.Trans
  356.     m3Apply Point2.Coord, M, Point2.Trans
  357.     m3Apply Point3.Coord, M, Point3.Trans
  358. End Sub
  359. ' Apply a transformation matrix to the object.
  360. Public Sub RayTraceable_ApplyFull(M() As Single)
  361.     ' Transform the points.
  362.     m3ApplyFull Point1.Coord, M, Point1.Trans
  363.     m3ApplyFull Point2.Coord, M, Point2.Trans
  364.     m3ApplyFull Point3.Coord, M, Point3.Trans
  365. End Sub
  366.  
  367. ' Draw the object with backfaces removed.
  368. ' Draw the whole wire frame for planes.
  369. Public Sub RayTraceable_DrawBackfacesRemoved(ByVal pic As PictureBox)
  370.     RayTraceable_DrawWireFrame pic
  371. End Sub
  372. ' Return the red, green, and blue components of
  373. ' the surface at the hit position.
  374. Public Sub RayTraceable_FindHitColor(ByVal depth As Integer, Objects As Collection, ByVal eye_x As Single, ByVal eye_y As Single, ByVal eye_z As Single, ByVal px As Single, ByVal py As Single, ByVal pz As Single, ByRef R As Integer, ByRef G As Integer, ByRef B As Integer)
  375. Dim Nx As Single
  376. Dim Ny As Single
  377. Dim Nz As Single
  378. Dim Vx As Single
  379. Dim Vy As Single
  380. Dim Vz As Single
  381. Dim NdotV As Single
  382. Dim ambient_kr As Single
  383. Dim ambient_kg As Single
  384. Dim ambient_kb As Single
  385. Dim diffuse_kr As Single
  386. Dim diffuse_kg As Single
  387. Dim diffuse_kb As Single
  388. Dim checker_x As Single
  389. Dim checker_y As Single
  390. Dim clr As Long
  391. Dim base_r As Single
  392. Dim base_g As Single
  393. Dim base_b As Single
  394.  
  395.     ' Find the unit normal at this point.
  396.     GetUnitNormal Nx, Ny, Nz
  397.  
  398.     ' Make sure the normal points towards the
  399.     ' center of projection.
  400.     Vx = EyeX - px
  401.     Vy = EyeY - py
  402.     Vz = EyeZ - pz
  403.     NdotV = Nx * Vx + Ny * Vy + Nz * Vz
  404.     If NdotV < 0 Then
  405.         Nx = -Nx
  406.         Ny = -Ny
  407.         Nz = -Nz
  408.     End If
  409.  
  410.     ' Get the point's checkerboard coordinates.
  411.     GetCheckerboardCoordinates checker_x, checker_y, px, py, pz
  412.     If checker_x >= 1 Then checker_x = checker_x - Int(checker_x)
  413.     If checker_y >= 1 Then checker_y = checker_y - Int(checker_y)
  414.  
  415.     ' Get the color of the texture picture at
  416.     ' this point.
  417.     InterpolateColor base_r, base_g, base_b, _
  418.         TexturePixels, _
  419.         checker_x * UBound(TexturePixels, 1), _
  420.         checker_y * UBound(TexturePixels, 2)
  421.     base_r = base_r / 255
  422.     base_g = base_g / 255
  423.     base_b = base_b / 255
  424.  
  425.     ' Get the hit color.
  426.     CalculateHitColor depth, Objects, Me, _
  427.         eye_x, eye_y, eye_z, _
  428.         px, py, pz, _
  429.         Nx, Ny, Nz, _
  430.         DiffuseFactor * base_r, DiffuseFactor * base_g, DiffuseFactor * base_b, _
  431.         AmbientFactor * base_r, AmbientFactor * base_g, AmbientFactor * base_b, _
  432.         SpecularK, SpecularN, _
  433.         ReflectedKr, ReflectedKg, ReflectedKb, IsReflective, _
  434.         TransmittedKr, TransmittedKg, TransmittedKb, TransN, n1, n2, IsTransparent, _
  435.         R, G, B
  436. End Sub
  437. ' See if the scanline plane with the indicated
  438. ' point and normal intersects this object.
  439. Public Sub RayTraceable_CullScanline(ByVal px As Single, ByVal py As Single, ByVal pz As Single, ByVal Nx As Single, ByVal Ny As Single, ByVal Nz As Single)
  440.     ' Do not scanline cull.
  441.     DoneOnThisScanline = False
  442. End Sub
  443. ' Return the value T for the point of intersection
  444. ' between the vector from point (px, py, pz) in
  445. ' the direction <vx, vy, vz>.
  446. '
  447. ' direct_calculation is true if we are finding the
  448. ' intersection from a viewing position ray. It is
  449. ' false if we are finding an reflected intersection
  450. ' or a shadow feeler.
  451. Public Function RayTraceable_FindT(ByVal direct_calculation As Boolean, ByVal px As Single, ByVal py As Single, ByVal pz As Single, ByVal Vx As Single, ByVal Vy As Single, ByVal Vz As Single) As Single
  452. Dim A As Single
  453. Dim B As Single
  454. Dim C As Single
  455. Dim D As Single
  456. Dim Nx As Single
  457. Dim Ny As Single
  458. Dim Nz As Single
  459. Dim denom As Single
  460. Dim t As Single
  461. Dim Cx As Single
  462. Dim Cy As Single
  463. Dim Cz As Single
  464. Dim dx As Single
  465. Dim dy As Single
  466. Dim dz As Single
  467. Dim X As Single
  468. Dim Y As Single
  469. Dim Z As Single
  470. Dim checker_x As Single
  471. Dim checker_y As Single
  472.  
  473.     ' See if we have been culled.
  474.     If direct_calculation And DoneOnThisScanline Then
  475.         RayTraceable_FindT = -1
  476.         Exit Function
  477.     End If
  478.  
  479.     ' Find the unit normal at this point.
  480.     GetUnitNormal Nx, Ny, Nz
  481.  
  482.     ' Compute the plane's parameters.
  483.     A = Nx
  484.     B = Ny
  485.     C = Nz
  486.     D = -(Nx * Point1.Trans(1) + _
  487.           Ny * Point1.Trans(2) + _
  488.           Nz * Point1.Trans(3))
  489.  
  490.     ' If the denominator = 0, the ray is parallel
  491.     ' to the plane so there's no intersection.
  492.     denom = A * Vx + B * Vy + C * Vz
  493.     If denom = 0 Then
  494.         RayTraceable_FindT = -1
  495.         Exit Function
  496.     End If
  497.  
  498.     ' Solve for t.
  499.     t = -(A * px + B * py + C * pz + D) / denom
  500.  
  501.     ' If there is no positive t value, there's no
  502.     ' intersection in this direction.
  503.     If t < 0.01 Then
  504.         RayTraceable_FindT = -1
  505.         Exit Function
  506.     End If
  507.  
  508.     ' Get the point of intersection with the plane.
  509.     X = px + t * Vx
  510.     Y = py + t * Vy
  511.     Z = pz + t * Vz
  512.  
  513.     ' See if the point is on a square.
  514.     If GetCheckerboardCoordinates(checker_x, checker_y, X, Y, Z) Then
  515.         ' The point is on a square.
  516.         ' We had a hit.
  517.         If direct_calculation Then HadHit = True
  518.         RayTraceable_FindT = t
  519.     Else
  520.         ' The point is not on a square.
  521.         RayTraceable_FindT = -1
  522.     End If
  523. End Function
  524. ' Return the minimum and maximum distances from
  525. ' this point.
  526. ' Use the wireframe points.
  527. Private Sub RayTraceable_GetRminRmax(new_min As Single, new_max As Single, ByVal X As Single, ByVal Y As Single, ByVal Z As Single)
  528. Dim dx As Single
  529. Dim dy As Single
  530. Dim dz As Single
  531. Dim px As Single
  532. Dim py As Single
  533. Dim pz As Single
  534. Dim v1x As Single
  535. Dim v1y As Single
  536. Dim v1z As Single
  537. Dim v2x As Single
  538. Dim v2y As Single
  539. Dim v2z As Single
  540. Dim i As Integer
  541. Dim j As Integer
  542. Dim dist As Single
  543.  
  544.     new_min = 1E+30
  545.     new_max = -1E+30
  546.  
  547.     ' Get the square vectors.
  548.     px = Point1.Trans(1)
  549.     py = Point1.Trans(2)
  550.     pz = Point1.Trans(3)
  551.     v1x = Point2.Trans(1) - px
  552.     v1y = Point2.Trans(2) - py
  553.     v1z = Point2.Trans(3) - pz
  554.     v2x = Point3.Trans(1) - px
  555.     v2y = Point3.Trans(2) - py
  556.     v2z = Point3.Trans(3) - pz
  557.  
  558.     For i = 0 To NumSquares1 Step NumSquares1
  559.         For j = 0 To NumSquares2 Step NumSquares2
  560.             dx = X - (px + i * v1x + j * v2x)
  561.             dy = Y - (py + i * v1y + j * v2y)
  562.             dz = Z - (pz + i * v1z + j * v2z)
  563.             dist = Sqr(dx * dx + dy * dy + dz * dz)
  564.             If new_min > dist Then new_min = dist
  565.             If new_max < dist Then new_max = dist
  566.         Next j
  567.     Next i
  568. End Sub
  569. ' Reset the ForeverCulled flag.
  570. Private Sub RayTraceable_ResetCulling()
  571.     ForeverCulled = False
  572.     HadHitOnPreviousScanline = False
  573. End Sub
  574.  
  575.  
  576.